<?php
/**
 * $Id: sql.class.php 324 2006-02-21 16:55:23Z tito $
 *
 * FGS is the legal property of its developers, whose names are too numerous
 * to list here.  Please refer to the COPYRIGHT file distributed with this
 * source distribution.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */ 

$fgssql_stats = array();
 
class fgsSql {

	// Configuration sql
	var $_host = '';
	var $_user = '';
	var $_pass = '';
	var $_base = '';
	var $_link;
	var $_res;

	// Connexion sur la base
	function fgsSql($host, $base, $user, $pass) {

		$this->_host = $host;
		$this->_base = $base;
		$this->_user = $user;
		$this->_pass = $pass;
	
		$this->_link = mysql_connect($this->_host, $this->_user, $this->_pass);
		if (!$this->_link) {
			$this->last_error = 'mysql: unable to connect to database';
			return false;
		}
	
		if (!empty($base))
			$this->database($base);
			
	}

	function stats() {
		global $fgssql_stats;
		return $fgssql_stats;
	}

	function database($base) {
		$this->_base = $base;
		if (!mysql_select_db($this->_base, $this->_link)) {
			$this->last_error = 'mysql: database doesn\'t exist';
			return false;
		}
		return true;
	}

	// create a dabatase
	function createDatabase($name) {
		$query = sprintf('CREATE DATABASE `%s`', $this->escapeStr($name));
		$res = $this->query($query);
		if (!$res)
			$this->last_error = mysql_error();
		return $res;
	}

	// check if class is in error
	function isError() {
		return !empty($this->last_error);
	}

	// return last error
	function error() {
		return $this->last_error;
	}

	// disconnect from the base
	function end() {
		mysql_close($this->_link);  
	}

	// execute a query
	function query($req) {
		global $fgssql_stats;
		
		$t_start = fgsUtils::mtimef();
		$this->_res = mysql_query($req, $this->_link);
		$t_end = fgsUtils::mtimef();

		$fgssql_stats[] = $t_end - $t_start;
		
		return $this->_res;
	}

	// fetch all result
	function fetchAll($res = null) {
		if ($res == null) 
			$res = & $this->_res;
		$tab = array();
		while ($e = mysql_fetch_array($res, MYSQL_ASSOC)) {
			if (!empty($e['id']))
				$tab[$e['id']] = $e;
			else
				$tab[] = $e;
		}
		return $tab;
	}

	// fetch all num (numeric index) 
	function fetchNumAll($res = null) {
		if ($res == null) 
			$res = & $this->_res;
		$tab = array();
		$i = 0;
		while ($e = mysql_fetch_array($res, MYSQL_NUM)) {
			$tab[$i++] = $e;
		}
		return $tab;
	}

	// fetch one line 
	function getline($res = null) {
		if ($res == null) 
			$res = & $this->_res;
		return mysql_fetch_array($res, MYSQL_ASSOC);
	}

	// fetch one line (numeric key) 
	function fetchNum($res = null) {
		if ($res == null) 
			$res = & $this->_res;
		return mysql_fetch_array($res, MYSQL_NUM);
	}

	// free data 
	function free($res = null) {
		if ($res == null) 
			$res = & $this->_res;
		mysql_free_result($res);
	}

	// get ID of last insertion (after an INSERT)
	function getLastID() {
		return mysql_insert_id();
	}

	// return num rows (after a SELECT)
	function nbrows($res = null) {
		if ($res == null) 
			$res = & $this->_res;
		return mysql_num_rows($res);
	}

	// return changed row (after an UPDATE)
	function affrows($res = null) {
		if ($res == null) 
			$res = & $this->_res;
		return mysql_affected_rows($this->_link);
	}

	// escape a string
	function escapeStr($str) {
		return mysql_real_escape_string($str);
	}

	// import an xml description
	function importXML($filename, $droptable = false) {
		$import = new fgsSqlImporter($this, $filename, $droptable);
		$import->import();
		return !$this->isError();
	}

}


class fgsSqlImporter {

	var $filename = '';
	var $sql = null;
	var $droptable = false;
	var $create = array();
	var $insert = array();

	function fgsSqlImporter(& $sql, $filename, $droptable) {
		$this->filename = $filename;
		$this->sql = & $sql;
		$this->droptable = $droptable ? true : false;
	} 

	function import() {
		
		$data = file_get_contents($this->filename);

		$xml_parser = xml_parser_create();
		xml_set_object($xml_parser, $this);
		xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
		xml_set_element_handler($xml_parser, '_startElement', '_endElement');
		xml_set_character_data_handler($xml_parser, '_characterData');
		
		if (!xml_parse($xml_parser, $data, strlen($data))) {
				$this->sql->last_error(sprintf('mysql: import: XML error : %s at line %d',
						xml_error_string(xml_get_error_code($xml_parser)),
						xml_get_current_line_number($xml_parser)));
				return false;
		}
		xml_parser_free($xml_parser);

		foreach ($this->create as $table => $query) {
			if ($this->droptable) {
				$q = sprintf('DROP TABLE `%s`', $table);
				if (!$this->sql->query($q)) {
					$this->sql->last_error = sprintf('unable to drop table %s : %s', $table, mysql_error($this->sql->_link));
					# return false;
				}
			}
			if (!$this->sql->query($query)) {
				$this->sql->last_error = sprintf('unable to create table %s : %s', $table, mysql_error($this->sql->_link));
				return false;
			}
		}
			
		foreach ($this->insert as $table => $query) {
			if (!$this->sql->query($query)) {
				$this->sql->last_error = sprintf('unable to insert data into %s : %s', $table, mysql_error($this->sql->_link));
				return false;
			}
		}
		
		return true;
	}

	function _startElement($parser, $name, $attrs) {
		if ($name == 'table')	{
			$this->command = 'create';
			$this->table = $attrs['name'];
		} else if ($name == 'data')	{
			$this->command = 'insert';
			$this->table = $attrs['table'];
		}
	}

	function _endElement($parser, $name) {
	}

	function _characterData($parser, $query) {
		switch ($this->command) {
			case 'create':
				$this->create[$this->table] .= $query;
				break;
			case 'insert':
				$this->insert[$this->table] .= $query;
				break;
		}
	}

}

?>
